/*
 * Copyright (C) 2008 GeoScheduler team, as stated on <http://www.geoscheduler.org/authors>.
 * 
 * This file is part of GeoScheduler.
 * 
 * GeoScheduler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GeoScheduler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with GeoScheduler. If not, see <http://www.gnu.org/licenses/>.
 */
package org.geoscheduler.android.tools;

import java.util.Hashtable;

import org.geoscheduler.model.Event;
import org.geoscheduler.model.Identifiable;
import org.geoscheduler.model.Location;
import org.geoscheduler.model.RemoteIdentifiable;
import org.geoscheduler.model.Tag;
import org.geoscheduler.model.TagEvent;
import org.geoscheduler.model.Event.AlertType;

import android.content.ContentValues;
import android.database.Cursor;

/**
 * Tools for local data mapping
 * 
 * @author paja
 */
public final class DBModel {

	public static ContentValues getContentValues(Object inst) {
		ContentValues ret = null;
		
		if (inst instanceof Event) {
			ret = new ContentValues();
			Event event = (Event) inst;
			ret.put(EventCols.VERSION, event.getVersion());
			ret.put(EventCols.EVENT_TYPE, event.getEventType());
			ret.put(EventCols.TITLE, event.getTitle());
			ret.put(EventCols.DESCRIPTION, event.getDescription());
			ret.put(EventCols.TIME_CREATED, event.getTimeCreated() == null ? null : DateTimeHelper.formatISO8601(event.getTimeCreated()));
			ret.put(EventCols.TIME_FROM, event.getTimeFrom() == null ? null : DateTimeHelper.formatISO8601(event.getTimeFrom()));
			ret.put(EventCols.TIME_TO, event.getTimeTo() == null ? null : DateTimeHelper.formatISO8601(event.getTimeTo()));
			ret.put(EventCols.LAST_ALERT, event.getLastAlert() == null ? null : DateTimeHelper.formatISO8601(event.getLastAlert()));
			ret.put(EventCols.ALERT_TYPE, event.getAlertType());
			ret.put(EventCols.REPEAT_TYPE, event.getRepeatType());
			ret.put(EventCols.LAST_ALERT_LAT, event.getLastAlertLat());
			ret.put(EventCols.LAST_ALERT_LON, event.getLastAlertLon());
			ret.put(EventCols.PROPERTIES, event.getProperties());
			ret.put(EventCols.REMOTE_ID, event.getRemoteId());

			if (event.getAlertTypeEnum() == AlertType.LOCATION
					|| event.getAlertTypeEnum() == AlertType.LOCATION_OR_TIME
					|| event.getAlertTypeEnum() == AlertType.LOCATION_TIME
					|| event.getAlertTypeEnum() == AlertType.LOCATION_XOR_TIME) {
								  
				ret.put(EventCols.LAT, event.getLocation().getLat());
				ret.put(EventCols.LAT_LO, event.getLocation().getLatLo());
				ret.put(EventCols.LAT_HI, event.getLocation().getLatHi());
				ret.put(EventCols.LON, event.getLocation().getLon());
				ret.put(EventCols.LON_LO, event.getLocation().getLonLo());
				ret.put(EventCols.LON_HI, event.getLocation().getLonHi());
				ret.put(EventCols.RADIUS, event.getLocation().getRadius());
				ret.put(EventCols.REMOTE_ID_LOCATION, event.getLocation().getRemoteId());
			}
		} else
		if (inst instanceof Tag) {
			ret = new ContentValues();
			Tag tag = (Tag) inst;
			ret.put(TagCols.VERSION, tag.getVersion());
			ret.put(TagCols.NAME, tag.getName());
			ret.put(TagCols.COUNTRY, tag.getCountry());
		} else
		if (inst instanceof TagEvent) {
			ret = new ContentValues();
			TagEvent tagEvent = (TagEvent) inst;
			ret.put(TagEventCols.ID_EVENT, tagEvent.getIdEvent());
			ret.put(TagEventCols.ID_TAG, tagEvent.getIdTag());
		}
		
		return ret;
	}

	public static void fillContentValues(Cursor cur, Object inst) {		
		if (inst instanceof Event) {
			Event event = (Event) inst;
			event.setId(cur.getLong(EventCols.COLUMN_IDXS.get(EventCols.ID)));			
			event.setVersion(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.VERSION)));
			event.setEventType(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.EVENT_TYPE)));
			event.setTitle(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.TITLE)));
			event.setDescription(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.DESCRIPTION)));
			event.setTimeCreated(DateTimeHelper.parseISO8601(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.TIME_CREATED))));
			event.setTimeFrom(DateTimeHelper.parseISO8601(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.TIME_FROM))));
			event.setTimeTo(DateTimeHelper.parseISO8601(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.TIME_TO))));
			event.setLastAlert(DateTimeHelper.parseISO8601(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.LAST_ALERT))));
			event.setAlertType(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.ALERT_TYPE)));
			event.setRepeatType(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.REPEAT_TYPE)));
			event.setLastAlertLat(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.LAST_ALERT_LAT)));
			event.setLastAlertLon(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.LAST_ALERT_LON)));
			event.setProperties(cur.getString(EventCols.COLUMN_IDXS.get(EventCols.PROPERTIES)));
			event.setRemoteId(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.REMOTE_ID)));
			
			Location loc = null;
			if (event.getAlertTypeEnum() == AlertType.LOCATION
					|| event.getAlertTypeEnum() == AlertType.LOCATION_OR_TIME
					|| event.getAlertTypeEnum() == AlertType.LOCATION_TIME
					|| event.getAlertTypeEnum() == AlertType.LOCATION_XOR_TIME) {
				
				loc = new Location();  
				loc.setId(cur.getLong(EventCols.COLUMN_IDXS.get(EventCols.ID)));
				loc.setLat(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.LAT)));
				loc.setLon(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.LON)));
				loc.setRadius(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.RADIUS)));
				loc.setRemoteId(cur.getInt(EventCols.COLUMN_IDXS.get(EventCols.REMOTE_ID_LOCATION)));
			}
			event.setLocation(loc);
		} else
		if (inst instanceof Tag) {
			Tag tag = (Tag) inst;
			tag.setId(cur.getLong(TagCols.COLUMN_IDXS.get(TagCols.ID)));			
			tag.setVersion(cur.getInt(TagCols.COLUMN_IDXS.get(TagCols.VERSION)));
			tag.setName(cur.getString(TagCols.COLUMN_IDXS.get(TagCols.NAME)));
			tag.setCountry(cur.getString(TagCols.COLUMN_IDXS.get(TagCols.COUNTRY)));
		}
	}

	public static String getTableName(Object inst) {
		if (inst instanceof Event) {
			return EventCols.TABLE_NAME;
		} else
		if (inst instanceof Tag) {
			return TagCols.TABLE_NAME;
		} else
		if (inst instanceof TagEvent) {
			return TagEventCols.TABLE_NAME;
		}
		
		return null;
	}

	public static String[] getColumnNames(Object inst) {
		if (inst instanceof Event) {
			return EventCols.COLUMNS_ALL;
		} else
		if (inst instanceof Tag) {
			return TagCols.COLUMNS_ALL;
		} else
		if (inst instanceof TagEvent) {
			return TagEventCols.COLUMNS_ALL;
		}
		
		return null;
	}

	public static Identifiable getFreshInstance(Object inst) {
		if (inst instanceof Event) {
			return new Event();
		}
		
		return null;
	}

	public static String getIDField(Identifiable inst) {
		if (inst instanceof Event) {
			return EventCols.ID;
		} else
		if (inst instanceof Tag) {
			return TagCols.ID;
		}
		
		return null;
	}

	public static String getRemoteIDField(RemoteIdentifiable inst) {
		if (inst instanceof Event) {
			return EventCols.REMOTE_ID;
		} 
		
		return null;
	}

	public static Hashtable<String, Integer> getInverseMapping(String values[]) {
		Hashtable<String, Integer> ret = new Hashtable<String, Integer>();
		
		int i = 0;
		for (String val: values) {
			ret.put(val, new Integer(i++));
		}
		
		return ret;
	}
	
	public static final class EventCols {

		public static final String TABLE_NAME = "GS_EVENT";
		
		public static final String ID = "id";

		public static final String VERSION = "version";
		public static final String EVENT_TYPE = "event_type";
		public static final String TITLE = "title";
		public static final String DESCRIPTION = "description";
		public static final String TIME_CREATED = "time_created";
		public static final String TIME_FROM = "time_from";
		public static final String TIME_TO = "time_to";
		public static final String LAST_ALERT = "last_alert";
		public static final String ALERT_TYPE = "alert_type";
		public static final String REPEAT_TYPE = "repeat_type";
		public static final String LAST_ALERT_LAT = "last_alert_lat";
		public static final String LAST_ALERT_LON = "last_alert_lon";
		public static final String PROPERTIES = "properties";
		public static final String REMOTE_ID = "remote_id";
		
		public static final String LON = "lon";
		public static final String LAT = "lat";
		public static final String RADIUS = "radius";
		public static final String LAT_LO = "lat_lo";
		public static final String LAT_HI = "lat_hi";
		public static final String LON_LO = "lon_lo";
		public static final String LON_HI = "lon_hi";
		public static final String REMOTE_ID_LOCATION = "remote_id_location";

		public static final String[] COLUMNS_ALL = new String[] {
				ID,
				VERSION,
				EVENT_TYPE,
				TITLE,
				DESCRIPTION,
				TIME_CREATED,
				TIME_FROM,
				TIME_TO,
				LAST_ALERT,
				ALERT_TYPE,
				REPEAT_TYPE,
				LAST_ALERT_LAT,
				LAST_ALERT_LON,
				PROPERTIES,
				REMOTE_ID,
				LON,
				LAT,
				RADIUS,
				LAT_LO,
				LAT_HI,
				LON_LO,
				LON_HI,
				REMOTE_ID_LOCATION};
		
		public static final Hashtable<String, Integer> COLUMN_IDXS = getInverseMapping(COLUMNS_ALL);
	}
	
	public static final class TagCols {

		public static final String TABLE_NAME = "GS_TAG";
		
		public static final String ID = "id";
		public static final String VERSION = "version";
		public static final String NAME = "name";
		public static final String COUNTRY = "country";

		public static final String[] COLUMNS_ALL = new String[] {
				ID,
				VERSION,
				NAME,
				COUNTRY};
		
		public static final Hashtable<String, Integer> COLUMN_IDXS = getInverseMapping(COLUMNS_ALL);
	}

	public static final class TagEventCols {

		public static final String TABLE_NAME = "GS_EVENT_GS_TAG";
		
		public static final String ID_EVENT = "id_event";
		public static final String ID_TAG = "id_tag";

		public static final String[] COLUMNS_ALL = new String[] {
			ID_EVENT,
			ID_TAG};
		
		public static final Hashtable<String, Integer> COLUMN_IDXS = getInverseMapping(COLUMNS_ALL);
	}	
}
